Данные были выбраны по искам страховщиков страховой(-ым) комании(-ям) в отношении автострахования в США. В датасете представлена следующая информация по каждому иску: данные о клиенте (id, образование, пол, занятость и др.), о страховке (канал продаж, ежемесячная плата, срок действия, кол-во месяцев с прошлого требования и др.), об автомобиле, и непосредственно о требовании (размер, причина, результат и др.). Всего в датасете 25 столбцов-характеристик и 9135 строк-объектов.
Определить влияющие факторы и построить прогнозирующую модель результата иска (удовлетворен/не удовлетворен) для выявления клиентов, которым чаще всего удовлетворяют иски, чтобы повышать понимать, какие расходы может понести страховая компания
import numpy as np
import pandas as pd
import os as os
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
import pydotplus
import xgboost as xgb
import eli5
from sklearn import model_selection
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.externals.six import StringIO
from sklearn.linear_model import LogisticRegression
from IPython.display import Image
from sklearn.tree import export_graphviz
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.ensemble import RandomForestClassifier
from sklearn import tree
warnings.filterwarnings('ignore')
sns.set_style('whitegrid')
plt.rcParams["patch.force_edgecolor"] = True
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
df = pd.read_csv('Claims and Weather Sample.csv')
df.head()
df = df.drop(['Customer', 'State Code'], axis=1)
df.head()
df.tail()
df.shape
df.describe()
df.info()
cols = ['Claim Amount', 'Total Claim Amount', 'Income', 'Monthly Premium Auto', 'EmploymentStatus', 'Gender',
'Response','Marital Status']
sns.pairplot(df[cols], hue='EmploymentStatus', palette='Set1', size=6)
По графику распределения "доходов" истцов видно, что больше всего истцов с нулевым доходом
Возможно наличие связи между "Суммой иска" и "Ежемесячный платеж по автостраховке"; "Итоговой суммой иска" и "Ежемесячнаый платеж по автостраховке", и логично было бы предположить связь между "Суммой иска" и "Итоговой суммой иска"
print("График распределения Claim Amount:", round(df[df['Claim Amount'] < 1000].shape[0]/df.shape[0]*100, 2), '% исков с суммой требования < 1000$')
print("График распределения Total Claim Amount:", round(df[df['Total Claim Amount'] < 600].shape[0]/df.shape[0]*100, 2), '% исков, где итоговая исковая сумма составляет < 600$')
print("График распределения Income:", round(df[df['Income'] == 0].shape[0]/df.shape[0]*100, 2), '% исков от клиентов с доходом равным 0$')
sns.distplot(df['Months Since Last Claim'], kde=False, bins=20)
sns.distplot(df['Months Since Policy Inception'], kde=False, bins=20)
cols2 = ['Claim Amount', 'Total Claim Amount', 'Income', 'Monthly Premium Auto', 'EmploymentStatus', 'Gender',
'Response','Marital Status']
sns.pairplot(df[cols2], hue='Response', palette='Set1', size=5)
sns.set(font_scale=1.5)
matr_corr = sns.heatmap(df[cols].corr(),
cbar=True,
annot=True)
Y_feature = df['Response'].apply(lambda x: 0 if x == 'No' else 1)
Y_feature
X = df.drop(['Customer', 'Response'], 1)
X_numeric = X.select_dtypes(include='number')
X_object = X.select_dtypes(exclude='number')
X_object['Effective To Date'] = pd.to_datetime(pd.to_datetime(X_object['Effective To Date'],
infer_datetime_format = True))
X_object['today'] = pd.to_datetime('2011-09-03')
X_numeric['Days until expire'] = (X_object['today'] - X_object['Effective To Date']).dt.days
X_object = X_object.drop(['today', 'Effective To Date'],1)
X_object = pd.get_dummies(X_object)
X_object.shape
X_features = pd.concat([X_numeric, X_object], axis=1)
X_features.shape
X_train, X_test, y_train, y_test = train_test_split(X_features, Y_feature, test_size=0.3, random_state=5)
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
logreg.score(X_train, y_train), logreg.score(X_test, y_test)
cv_logreg = cross_val_score(LogisticRegression(), X_train, y_train, cv=3)
print(cv_logreg,'\n', cv_logreg.mean())
logreg2 = LogisticRegression(C=5)
logreg2.fit(X_train, y_train)
logreg2.score(X_train, y_train), logreg2.score(X_test, y_test)
cv_logreg2 = cross_val_score(logreg2, X_train, y_train, cv=3)
print(cv_logreg2,'\n', cv_logreg2.mean())
Такое же значение, как и у кросс-валидации логрегрессии без регуляризации
dt_params = {
'criterion': ['gini', 'entropy'],
'max_depth': [3,5,7],
'min_samples_split': [3,5,7]
}
dt = DecisionTreeClassifier()
cv_dt = GridSearchCV(dt, dt_params, cv=5, scoring='f1')
cv_dt.fit(X_train, y_train)
cv_dt.best_estimator_
cv_dt.best_score_
preds = cv_dt.predict(X_test)
print(classification_report(y_test, preds))
print(confusion_matrix(y_test, preds))
pd.Series(y_test).value_counts()
dot_data = tree.export_graphviz(cv_dt.best_estimator_, out_file=None,
feature_names=X_features.columns)
graph = pydotplus.graph_from_dot_data(dot_data)
Image(graph.create_png())
# Можно сохранить дерево себе на память и разглядеть получше
graph.write_png('tree.png')
voting = VotingClassifier(estimators=[('lr', logreg), ('dt', dt), ('lr2', logreg2)], voting='hard')
voting.fit(X_train,y_train)
voting.score(X_train,y_train), voting.score(X_test,y_test)
cv_voting = cross_val_score(voting, X_train, y_train, cv=3)
print(cv_voting,'\n', cv_voting.mean())
Значение чуть больше, чем у логрегрессии
bg = BaggingClassifier(base_estimator=dt, n_estimators=100, random_state=18)
bg.fit(X_train,y_train)
bg.score(X_train,y_train), bg.score(X_test,y_test)
cv_bg = cross_val_score(bg, X_train, y_train, cv=3, scoring = "f1_macro")
print(cv_bg,'\n', cv_bg.mean())
Значение стало очень большим после того, как я заменил базу оценки с логрегрессии на дерево решений
X_train, X_test, y_train, y_test = train_test_split(X_features, Y_feature, test_size=0.3, random_state=18)
rf_params = {
'criterion': ['gini', 'entropy'],
'max_depth': [3,5,7],
'min_samples_split': [3,5,7],
'n_estimators': [100,300,500]
}
cv_rf = GridSearchCV(RandomForestClassifier(), rf_params, cv=5, scoring='f1', n_jobs=-1)
cv_rf.fit(X_train, y_train)
preds_rf = cv_rf.predict(X_test)
print(classification_report(y_test, preds_rf))
print(confusion_matrix(y_test, preds_rf))
X_train, X_test, y_train, y_test = train_test_split(X_features, Y_feature, test_size=0.3, random_state=18)
xgb_params = {
'max_depth': [3,5,7],
'n_estimators': [100,300,500],
'learning_rate': [0.01, 0.05, 0.1]
}
cv_xgb = GridSearchCV(xgb.XGBClassifier(), xgb_params, cv=5, scoring='f1', n_jobs=-1)
cv_xgb.fit(X_train, y_train)
preds_xgb = cv_xgb.predict(X_test)
print(classification_report(y_test, preds_xgb))
print(confusion_matrix(y_test, preds_xgb))
Здесь серьезное заявление на самую эффективную модель
et = ExtraTreesClassifier(n_estimators=100, max_features=5)
et.fit(X_train, y_train)
et.score(X_train, y_train), et.score(X_test, y_test)
cv_et = cross_val_score(et, X_train, y_train, cv=3)
print(cv_et,'\n', cv_et.mean())
Очень хорошая эффективность, но не самая высокая
gb = GradientBoostingClassifier(n_estimators=100)
gb.fit(X_train, y_train)
gb.score(X_train, y_train), gb.score(X_test, y_test)
cv_gb = cross_val_score(gb, X_train, y_train, cv=3)
print(cv_gb,'\n', cv_gb.mean())
Не самая высокая оценка